package com.yjw.rpc.v2;

import com.yjw.rpc.IoUtils;
import com.yjw.rpc.v1.ProcessHandler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @author: James Yin
 * @description:
 * @date: 2/11/2020 10:49 PM
 */
@Component
public class RpcProxyServer implements InitializingBean, ApplicationContextAware {

    private static final Map<String, Object> services = new ConcurrentHashMap<>();
    private static final Executor threadPool = Executors.newCachedThreadPool();
    private int port = 9090;

    /**
     * 启动Socket服务
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
            while (true) {
                Socket socket = serverSocket.accept();
                threadPool.execute(new ProcessHandler(socket, services));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IoUtils.close(serverSocket);
        }
    }

    /**
     * 通过Spring，获得定义了RpcService注解的service
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Object> servicesMap = applicationContext.getBeansWithAnnotation(RpcService.class);
        if (CollectionUtils.isEmpty(servicesMap)) {
            return;
        }
        for (Object serviceBean : servicesMap.values()) {
            RpcService rpcService = serviceBean.getClass().getAnnotation(RpcService.class);
            String serviceName = rpcService.value().getName();
            services.put(serviceName, serviceBean);
        }
    }
}
